package com.eian.boot.module.common.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import com.eian.boot.common.core.model.CommonResult;
import com.eian.boot.common.core.utils.BeanCopierUtils;
import com.eian.boot.common.id.IdHelper;
import com.eian.boot.common.id.mapper.IdFormatConfigMapper;
import com.eian.boot.common.id.mapper.IdSegmentMapper;
import com.eian.boot.common.id.model.BatchIdConfig;
import com.eian.boot.common.id.model.IdFormatConfigEntity;
import com.eian.boot.common.id.model.IdSegmentEntity;
import com.eian.boot.common.id.service.IdFormatService;
import com.eian.boot.module.common.model.dto.*;
import com.eian.boot.module.common.model.vo.BatchIdResultVO;
import com.eian.boot.module.common.model.vo.IdConfigVO;
import com.eian.boot.module.common.model.vo.IdResultVO;
import com.eian.boot.module.common.model.vo.IdSegmentVO;
import com.mybatisflex.core.query.QueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.util.Collection;
import java.util.List;

/**
 * ID生成器接口
 *
 * @author alex.meng
 * @createTime 2025-10-15
 * @description Id取号
 */
@Tag(name = "ID生成器")
@RestController
@RequestMapping("/common/id-generator")
@RequiredArgsConstructor
public class IdGeneratorController {

    private final IdFormatConfigMapper formatConfigMapper;
    private final IdSegmentMapper segmentMapper;
    private final IdFormatService formatService;

    // ==================== UUID系列 ====================

    @SaIgnore
    @Operation(summary = "生成UUID（标准格式，带连字符）")
    @GetMapping("/uuid")
    public CommonResult<IdResultVO> generateUuid() {
        String id = IdHelper.uuid();
        return CommonResult.ok(IdResultVO.builder()
                .id(id)
                .build());
    }

    @SaIgnore
    @Operation(summary = "生成简化UUID（无连字符）")
    @GetMapping("/simple-uuid")
    public CommonResult<IdResultVO> generateSimpleUuid() {
        String id = IdHelper.simpleUuid();
        return CommonResult.ok(IdResultVO.builder()
                .id(id)
                .build());
    }

    // ==================== 雪花ID ====================

    @SaIgnore
    @Operation(summary = "生成雪花ID（数字形式）")
    @GetMapping("/snowflake")
    public CommonResult<IdResultVO> generateSnowflakeId() {
        long id = IdHelper.snowflakeId();
        return CommonResult.ok(IdResultVO.builder()
                .id(String.valueOf(id))
                .numericId(id)
                .build());
    }

    @SaIgnore
    @Operation(summary = "生成雪花ID（字符串形式）")
    @GetMapping("/snowflake-str")
    public CommonResult<IdResultVO> generateSnowflakeIdStr() {
        String id = IdHelper.snowflakeIdStr();
        return CommonResult.ok(IdResultVO.builder()
                .id(id)
                .build());
    }

    // ==================== 号段模式 ====================

    @SaIgnore
    @Operation(summary = "生成号段ID")
    @PostMapping("/segment/generate")
    public CommonResult<IdResultVO> generateSegmentId(@Valid @RequestBody GenerateSegmentIdRequest request) {
        long id = IdHelper.nextSegmentId(request.getBizType());
        return CommonResult.ok(IdResultVO.builder()
                .id(String.valueOf(id))
                .numericId(id)
                .build());
    }

    // ==================== 序列号 ====================

    @SaIgnore
    @Operation(summary = "生成序列号")
    @PostMapping("/sequence/generate")
    public CommonResult<IdResultVO> generateSequence(@Valid @RequestBody GenerateSequenceRequest request) {
        long id = IdHelper.nextSequence(request.getBizType());
        return CommonResult.ok(IdResultVO.builder()
                .id(String.valueOf(id))
                .numericId(id)
                .build());
    }

    // ==================== 自定义格式化 ====================

    @SaIgnore
    @Operation(summary = "根据数据库配置生成ID")
    @PostMapping("/generate")
    public CommonResult<IdResultVO> generateIdByConfig(@Valid @RequestBody GenerateIdByConfigRequest request) {
        String id = IdHelper.generateId(request.getBizType());
        return CommonResult.ok(IdResultVO.builder()
                .id(id)
                .build());
    }

    @SaIgnore
    @Operation(summary = "根据数据库配置格式化ID")
    @PostMapping("/format")
    public CommonResult<IdResultVO> formatIdByConfig(@Valid @RequestBody FormatIdRequest request) {
        String id = IdHelper.formatIdByConfig(request.getBizType(), request.getRawId());
        return CommonResult.ok(IdResultVO.builder()
                .id(id)
                .build());
    }

    // ==================== 混淆功能 ====================

    @SaIgnore
    @Operation(summary = "混淆ID")
    @PostMapping("/obfuscate")
    public CommonResult<IdResultVO> obfuscateId(@Valid @RequestBody ObfuscateIdRequest request) {
        long obfuscatedId = IdHelper.obfuscateId(request.getId());
        return CommonResult.ok(IdResultVO.builder()
                .id(String.valueOf(obfuscatedId))
                .numericId(obfuscatedId)
                .build());
    }

    @SaIgnore
    @Operation(summary = "反混淆ID")
    @PostMapping("/deobfuscate")
    public CommonResult<IdResultVO> deobfuscateId(@Valid @RequestBody DeobfuscateIdRequest request) {
        long originalId = IdHelper.deobfuscateId(request.getObfuscatedId());
        return CommonResult.ok(IdResultVO.builder()
                .id(String.valueOf(originalId))
                .numericId(originalId)
                .build());
    }

    // ==================== 批量生成 ====================

    @SaIgnore
    @Operation(summary = "批量生成ID（基于数据库模板配置）")
    @PostMapping("/batch")
    public CommonResult<BatchIdResultVO> batchGenerate(@Valid @RequestBody BatchGenerateRequest request) {
        Collection<String> ids;
        if (Boolean.TRUE.equals(request.getUnique())) {
            ids = IdHelper.generateBatchUnique(request.getBizType(), request.getCount());
        } else {
            ids = IdHelper.generateBatch(request.getBizType(), request.getCount());
        }
        return CommonResult.ok(BatchIdResultVO.builder()
                .ids(ids)
                .count(ids.size())
                .build());
    }

    @SaIgnore
    @Operation(summary = "批量生成ID（自定义配置）")
    @PostMapping("/batch-custom")
    public CommonResult<BatchIdResultVO> batchGenerateByConfig(@Valid @RequestBody BatchGenerateByConfigRequest request) {
        BatchIdConfig config = BeanCopierUtils.copy(request, BatchIdConfig.class);

        Collection<String> ids;
        if (Boolean.TRUE.equals(request.getUnique())) {
            ids = IdHelper.generateBatchUnique(config, request.getCount());
        } else {
            ids = IdHelper.generateBatch(config, request.getCount());
        }
        return CommonResult.ok(BatchIdResultVO.builder()
                .ids(ids)
                .count(ids.size())
                .build());
    }

    // ==================== ID格式配置管理 ====================

    @SaIgnore
    @Operation(summary = "创建ID格式配置")
    @PostMapping("/config")
    public CommonResult<IdConfigVO> createConfig(@Valid @RequestBody CreateIdConfigRequest request) {
        IdFormatConfigEntity entity = BeanCopierUtils.copy(request, IdFormatConfigEntity.class);
        formatConfigMapper.insert(entity);

        // 刷新缓存
        formatService.refreshCache(entity.getBizType());

        return CommonResult.ok(BeanCopierUtils.copy(entity, IdConfigVO.class));
    }

    @SaIgnore
    @Operation(summary = "更新ID格式配置")
    @PutMapping("/config")
    public CommonResult<IdConfigVO> updateConfig(@Valid @RequestBody UpdateIdConfigRequest request) {
        IdFormatConfigEntity entity = formatConfigMapper.selectOneById(request.getBizType());
        if (entity == null) {
            return CommonResult.fail("配置不存在：" + request.getBizType());
        }
        BeanCopierUtils.copy(request, entity);
        formatConfigMapper.update(entity);
        // 刷新缓存
        formatService.refreshCache(entity.getBizType());
        return CommonResult.ok(BeanCopierUtils.copy(entity, IdConfigVO.class));
    }

    @SaIgnore
    @Operation(summary = "删除ID格式配置")
    @DeleteMapping("/config/{bizType}")
    public CommonResult<Void> deleteConfig(@PathVariable String bizType) {
        formatConfigMapper.deleteById(bizType);
        // 清除缓存
        formatService.clearCache(bizType);
        return CommonResult.ok();
    }

    @SaIgnore
    @Operation(summary = "查询单个ID格式配置")
    @GetMapping("/config/{bizType}")
    public CommonResult<IdConfigVO> getConfig(@PathVariable String bizType) {
        IdFormatConfigEntity entity = formatConfigMapper.selectOneById(bizType);
        if (entity == null) {
            return CommonResult.fail("配置不存在：" + bizType);
        }
        return CommonResult.ok(BeanCopierUtils.copy(entity, IdConfigVO.class));
    }

    @SaIgnore
    @Operation(summary = "查询ID格式配置列表")
    @PostMapping("/config/list")
    public CommonResult<List<IdConfigVO>> listConfigs(@RequestBody QueryIdConfigRequest request) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .from(IdFormatConfigEntity.class);

        if (request.getBizType() != null && !request.getBizType().isEmpty()) {
            queryWrapper.where("biz_type LIKE {0}", "%" + request.getBizType() + "%");
        }
        if (request.getIdContentType() != null && !request.getIdContentType().isEmpty()) {
            queryWrapper.where("id_content_type = {0}", request.getIdContentType());
        }
        if (request.getStatus() != null) {
            queryWrapper.where("status = {0}", request.getStatus());
        }

        queryWrapper.orderBy("biz_type", true);

        List<IdFormatConfigEntity> entities = formatConfigMapper.selectListByQuery(queryWrapper);
        List<IdConfigVO> vos = BeanCopierUtils.copyList(entities, IdConfigVO.class);

        return CommonResult.ok(vos);
    }

    @SaIgnore
    @Operation(summary = "刷新ID格式配置缓存")
    @PostMapping("/config/refresh-cache/{bizType}")
    public CommonResult<Void> refreshConfigCache(@PathVariable String bizType) {
        formatService.refreshCache(bizType);
        return CommonResult.ok();
    }

    @SaIgnore
    @Operation(summary = "清除所有ID格式配置缓存")
    @PostMapping("/config/clear-cache")
    public CommonResult<Void> clearAllConfigCache() {
        formatService.clearCache(null);
        return CommonResult.ok();
    }

    // ==================== ID号段配置管理 ====================

    @SaIgnore
    @Operation(summary = "创建ID号段配置")
    @PostMapping("/segment-config")
    public CommonResult<IdSegmentVO> createSegment(@Valid @RequestBody CreateIdSegmentRequest request) {
        IdSegmentEntity entity = BeanCopierUtils.copy(request, IdSegmentEntity.class);
        segmentMapper.insert(entity);

        return CommonResult.ok(BeanCopierUtils.copy(entity, IdSegmentVO.class));
    }

    @SaIgnore
    @Operation(summary = "更新ID号段配置")
    @PutMapping("/segment-config")
    public CommonResult<IdSegmentVO> updateSegment(@Valid @RequestBody UpdateIdSegmentRequest request) {
        IdSegmentEntity entity = segmentMapper.selectOneById(request.getBizType());
        if (entity == null) {
            return CommonResult.fail("号段配置不存在：" + request.getBizType());
        }

        // 只更新非空字段
        BeanCopierUtils.copy(request, entity);
        segmentMapper.update(entity);

        return CommonResult.ok(BeanCopierUtils.copy(entity, IdSegmentVO.class));
    }

    @SaIgnore
    @Operation(summary = "删除ID号段配置")
    @DeleteMapping("/segment-config/{bizType}")
    public CommonResult<Void> deleteSegment(@PathVariable String bizType) {
        segmentMapper.deleteById(bizType);
        return CommonResult.ok();
    }

    @SaIgnore
    @Operation(summary = "查询单个ID号段配置")
    @GetMapping("/segment-config/{bizType}")
    public CommonResult<IdSegmentVO> getSegment(@PathVariable String bizType) {
        IdSegmentEntity entity = segmentMapper.selectOneById(bizType);
        if (entity == null) {
            return CommonResult.fail("号段配置不存在：" + bizType);
        }

        return CommonResult.ok(BeanCopierUtils.copy(entity, IdSegmentVO.class));
    }

    @SaIgnore
    @Operation(summary = "查询ID号段配置列表")
    @GetMapping("/segment-config/list")
    public CommonResult<List<IdSegmentVO>> listSegments() {
        List<IdSegmentEntity> entities = segmentMapper.selectAll();
        List<IdSegmentVO> vos = BeanCopierUtils.copyList(entities, IdSegmentVO.class);

        return CommonResult.ok(vos);
    }
}
